package top.xxyu;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;

/**
 * 根据svn的change log，生成PSA与ESS的hotfix目录及文件
 * <p>
 * 方法1
 * 1 在项目右键属性Team-显示资源历史记录中找到需要生成hotfix的记录
 * 2 选中记录后点右键-Generate ChangeLog，选择svn log with affected paths
 * 3 将生成的日志文件拷贝到/svnlog/svnlog.log中
 * 4 在main方法中设置本机上psa和ess在tomcat中的目录basePsa和baseEss，输出目录desFolder
 * 5 运行
 * 6 使用生成的文件打包
 * <p>
 * 方法2
 * 1 在日志文件填写需要生成hotfix的文件相对路径，文件路径必须以M /CLOUD/PSA，A /CLOUD/PSA，M /CLOUD/ESS，A /CLOUD/ESS开头（M A为svn中的修改状态）
 * 如 M /CLOUD/PSA/src/main/webapp/cm/jsp/apinvoice/invoicePaymentInquery.jsp
 * 或 A /CLOUD/PSA/src/main/java/cn/com/norming/pr/web/dataImport/allocationsetimport/ImportAllocationset.java
 * 其中PSA_PERFIX ,ESS_PERFIX可以修改为自己的项目文件名。
 * 2 在main方法中设置本机上psa和ess在tomcat中的目录basePsa和baseEss，输出目录desFolder
 * 3 运行
 * 4 使用生成的文件打包
 *
 * @author tobin
 */
public class SvnDiffPack {

    private static String DASH = File.separator;
    private static String FLAG_DIFF = "Index: ";

    private static String PROJECT_PERFIX = DASH + "XYZH";//如不使用svnlog，可以修改为自己的项目文件名。
    private static String JAVA_SUFFIX = ".java";
    private static String CLASS_SUFFIX = ".class";

    private static String SRC_MAIN_JAVA = DASH + "base_src";
    private static String[] SRC_MAIN_JAVAS = new String[]{};
    /**
     * 打包文件数量
     */
    private static int fileCount = 0;
    /**
     * 打包文件 内部类数量
     */
    private static int file$Count = 0;
    /**
     * 打包文件java数量
     */
    private static int fileJavaCount = 0;
    /**
     * 打包文件js数量
     */
    private static int fileJsCount = 0;


    private static String SRC_MAIN_RESOURCES = DASH+"src"+DASH+"main"+DASH+"resources";
    //    private static String SRC_MAIN_WEBAPP = "/src/main/webapp";
    private static String SRC_MAIN_WEBAPP = "WebRoot";
    private static String WEB_INF = DASH+"WEB-INF";

    private static String DES_MAIN_JAVA = DASH+"WEB-INF"+DASH+"classes";
    private static String DES_MAIN_JAVA_ = "WEB-INF"+DASH+"classes";
    private static String DES_MAIN_RESOURCES = DASH+"WEB-INF"+DASH+"classes";
    private static String DES_MAIN_WEBAPP = "";

    private static String FOLDER_PSA = "psa_cpa";
    private static String FOLDER_ESS = "ess_cpa";

    public static LinkedList<String> parser(String fileAddr) {
        File logFile = new File(fileAddr);
        LinkedList<String> filePaths = new LinkedList<String>();
        LinkedList<String> filePathToVerify = new LinkedList<String>();
        BufferedReader reader;
        try {
            reader = new BufferedReader(new FileReader(logFile));
            String temp = reader.readLine();
            temp = formatPatch(temp);
            while (temp != null) {
                if (temp.startsWith(FLAG_DIFF)) {
                    filePaths.add(temp.substring(FLAG_DIFF.length(), temp.length()));
                }
                temp = reader.readLine();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        for (String t : filePathToVerify) {
            System.out.println("未处理：" + t);
        }
        return filePaths;
    }


    public static void copyFiles(LinkedList<String> filePaths, String srcFolder, String desFolder) {
        //清理
        File essRoot = new File(desFolder + "/" + FOLDER_ESS);
        if (essRoot.exists()) {
            FileHelper.deleteDir(essRoot);
            essRoot.delete();
        }
        //拷贝
        for (String filePath : filePaths) {
            fileCount++;
            filePath = formatPatch(filePath);
            String filePathFolder = filePath.substring(0, filePath.lastIndexOf(DASH) + 1);
            String name = filePath.substring(filePath.lastIndexOf(DASH) + 1, filePath.length());
            if (name.endsWith(JAVA_SUFFIX)) {
                //java文件，需要拷贝class
//                filePathFolder = filePathFolder.replace(SRC_MAIN_JAVA, DES_MAIN_JAVA);
                for (int i = 0; i < SRC_MAIN_JAVAS.length; i++) {
                    if(filePathFolder.contains(WEB_INF)){
                        break;
                    }
                    filePathFolder = filePathFolder.replace(SRC_MAIN_JAVAS[i], DES_MAIN_JAVA_);
                }
                filePathFolder = filePathFolder.replace(SRC_MAIN_RESOURCES, DES_MAIN_RESOURCES);
                final String finalName = name.replace(JAVA_SUFFIX, "");
                String oldPath = srcFolder+ DASH + filePathFolder + finalName + CLASS_SUFFIX;
                String newPath = desFolder + DASH + FOLDER_ESS + DASH + filePathFolder + finalName + CLASS_SUFFIX;
                FileHelper.copyFile(formatPatch(oldPath), formatPatch(newPath));
                System.out.println("---->" + newPath);
                //拷贝内部类
                File oldFolder = new File(srcFolder + DASH + filePathFolder);
                String[] files = oldFolder.list(new FilenameFilter() {
                    public boolean accept(File file, String filename) {
                        return filename.startsWith(finalName + "$") && filename.endsWith(CLASS_SUFFIX) ? true : false;
                    }
                });
                for (String file : files) {
                    oldPath = srcFolder + DASH + filePathFolder + file;
                    newPath = desFolder + DASH + FOLDER_ESS + DASH + filePathFolder + file;
                    System.out.println("---->" + newPath);
                    FileHelper.copyFile(formatPatch(oldPath), formatPatch(newPath));
                    file$Count++;
                }
                fileJavaCount++;
            } else {
                //非java文件，直接拷贝
                    for (int i = 0; i < SRC_MAIN_JAVAS.length; i++) {
                        if(filePathFolder.contains(WEB_INF)){
                            break;
                        }
                        filePathFolder = filePathFolder.replace(SRC_MAIN_JAVAS[i], DES_MAIN_JAVA_);
                    }
                    filePathFolder = filePathFolder.replace(SRC_MAIN_RESOURCES, DES_MAIN_RESOURCES);
                    filePathFolder = filePathFolder.replace(SRC_MAIN_WEBAPP, DES_MAIN_WEBAPP);
                    filePathFolder = filePathFolder.replace("classes_cfg", "classes");
                    String oldPath = srcFolder + DASH + filePathFolder + name;
                    String newPath = desFolder + DASH + FOLDER_ESS + DASH + filePathFolder + name;
                    System.out.println("---->" + formatPatch(newPath));
                    FileHelper.copyFile(formatPatch(oldPath), formatPatch(newPath));
                    fileJsCount++;
            }
        }
    }

    private static String formatPatch(String patch) {
//        if (!File.separator.equals("/")) {
//            return patch.replaceAll("/", "\\\\");
//        }
        patch = patch.replaceAll("/", Matcher.quoteReplacement(File.separator));
        patch = patch.replaceAll("\\\\", Matcher.quoteReplacement(File.separator));
        return patch;
    }

    /**
     * 获取项目配置包
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws SAXException
     */
    public static void getSrcPatch() throws ParserConfigurationException, IOException, SAXException {
        //创建一个DOM解析器工厂对象;
        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        //通过工厂对象创建DOM解析器
//        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        //解析文档
        InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("SRCClassPatch.xml");
        //doc 即为树状结构的存储对象,在内存中;
        Document document = documentBuilder.parse(resourceAsStream);
        List<String> srcList = new ArrayList<String>();
        NodeList classPathentry = document.getElementsByTagName("classpathentry");
        for (int i = 0; i < classPathentry.getLength(); i++) {
            NamedNodeMap attributes = classPathentry.item(i).getAttributes();
            if ("src".equals(attributes.getNamedItem("kind").getNodeValue())) {
                srcList.add(attributes.getNamedItem("path").getNodeValue());
            }
        }
        SRC_MAIN_JAVAS = srcList.toArray(new String[srcList.size()]);
        System.out.println(SRC_MAIN_JAVAS);
    }


    /**
     * 创建打包目的路径
     * @param properties
     * @return
     */
    private static String makeOutPatch(Properties properties) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH：mm：ss");
        String desFolder = properties.getProperty("out_hotfix_path")+"\\"+simpleDateFormat.format(new Date());
        if (!new File(desFolder).exists()) {
            new File(desFolder).mkdirs();
        }
        return desFolder;
    }

    /**
     * 获取tomcat路径
     * @param properties
     * @return
     * @throws IOException
     */
    private static String getTomcatWebappPath(Properties properties) throws IOException {
        String essBase = properties.getProperty("ess_cpa_tomcat_path");
        if (!new File(essBase).exists()) {
            System.out.println("ess_cpa目录不存在");
        }
        return essBase;
    }

    /**
     * 获取路径信息
     * @return
     * @throws IOException
     */
    private static Properties getPatchProperties() throws IOException {
        InputStream resource = Thread.currentThread().getContextClassLoader().getResourceAsStream("path.properties");
        Properties properties = new Properties();
        properties.load(resource);
        return properties;
    }



    public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException {
        getSrcPatch();
        try {
            Properties properties = getPatchProperties();
            String essBase = getTomcatWebappPath(properties);
            if (essBase == null) {
                return;
            }
            String desFolder = makeOutPatch(properties);
            String log = Thread.currentThread().getContextClassLoader().getResource("diff.log").getPath();
            LinkedList<String> filePaths = parser(log);
//            filePaths.forEach(System.out::println);
            copyFiles(filePaths, essBase, desFolder);
            System.out.println("打包完成！！！");
            System.out.println("全部文件：" + fileCount);
            System.out.println("Java文件：" + fileJavaCount);
            System.out.println("内部类文件：" + file$Count);
            System.out.println("Js文件：" + fileJsCount);
            System.out.println(desFolder);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

}

